import { ScaffoldCallToActionTour } from './index/ScaffoldCallToAction'

Similarly to Nuxt,
we define a new page by creating a new `.page.vue` file.

```vue
<!-- /pages/index.page.vue -->
<!-- Environment: Browser, Node.js -->

<template>
  This page is rendered to HTML and interactive: <Counter />
</template>

<script>
import Counter from '../components/Counter.vue'
export default { components: { Counter } }
</script>
```

By default, `vite-plugin-ssr` does Filesystem Routing.
```
FILESYSTEM                  URL
pages/index.page.vue        /
pages/about.page.vue        /about
```

We can also define a page's route with a *Route String* (for parameterized routes such as `/movies/:id`) or a *Route Function* (for full programmatic flexibility).

```js
// /pages/index.page.route.js
// Environment: Node.js (and Browser if we choose Client Routing)

// Note how the two files share the same base `/pages/index.page.`; this is how `vite-plugin-ssr`
// knows that `/pages/index.page.route.js` defines the route of `/pages/index.page.vue`.

// Route Function
export default pageContext => pageContext.url === '/'

// If we don't create a `.page.route.js` file then vite-plugin-ssr does Filesystem Routing
```

Unlike Nuxt, we define how our pages are rendered.

```js
// _default.page.server.js
// Environment: Node.js

import { createSSRApp, h } from 'vue'
import { renderToString } from '@vue/server-renderer'
import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr'

export { render }

async function render(pageContext) {
  const { Page, pageProps } = pageContext
  const app = createSSRApp({
    render: () => h(Page, pageProps)
  })

  const appHtml = await renderToString(app)

  const title = 'Vite SSR'

  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>${title}</title>
      </head>
      <body>
        <div id="app">${dangerouslySkipEscape(appHtml)}</div>
      </body>
    </html>`
}
```
```js
// _default.page.client.js
// Environment: Browser

import { createSSRApp, h } from 'vue'
import { getPage } from 'vite-plugin-ssr/client'

hydrate()

async function hydrate() {
  const pageContext = await getPage() // (`pageContext` is preloaded in production)
  const { Page, pageProps } = pageContext
  const app = createSSRApp({
    render: () => h(Page, pageProps)
  })
  app.mount('#app')
}
```

> You may see `import { createSSRApp, h } from 'vue'` for the first time
> but every SSR app actually uses `createSSRApp` and `h`.
>
> Nuxt abstracts this away from us and gives us a slightly faster getting started. But this also means that we
> loose control over a central piece of our app architecture and
> we'll eventually loose much more time circumventing Nuxt's limiting black box as we scale.
>
> The boilerplate `$ npm init vite-plugin-ssr@latest` provides a functioning setup
> that will require only small adaptations for most users.

The `render()` hook in `_default.page.server.js` gives us full control over how our pages are rendered to HTML,
and `_default.page.client.js` gives us full control over the browser-side code.
This control enables us to *easily* and *naturally* integrate any tool we want (Vuex, GraphQL, Service Worker, ...).

There are four suffixes:
 - `.page.js`: exports the page's root Vue component.
 - `.page.client.js`: defines the page's browser-side code.
 - `.page.server.js`: exports page hooks (always run in Node.js).
 - `.page.route.js`: exports the page's Route String or Route Function.

Instead of creating a `.page.client.js` and `.page.server.js` file for each page,
we can create `_default.page.client.js` and `_default.page.server.js` which apply as default for all pages.

The last two files we created are actually `_default.page.client.js` and `_default.page.server.js`,
which means that we can now create a new page just by defining a new `.page.vue` file (the `.page.route.js` file is optional).

The `_default` files can be overridden. For example, we can create a page with a different browser-side code than our other pages.

```js
// /pages/about.page.client.js

// This file is empty which means that the `/about` page has zero browser-side JavaScript.
```
```vue
<!-- /pages/about.page.vue -->

<template>
  This page is only rendered to HTML.
</template>
```

By also overriding the `render()` hook we can
even render a page with a completely different UI framework, e.g. React or another Vue version (for progressive Vue version upgrade).

Let's now have a look at how to fetch data.

```vue
<!-- /pages/star-wars/movie.page.vue -->
<!-- Environment: Browser, Node.js -->

<template>
  <h1>{{movie.title}}</h1>
  <p>Release Date: {{movie.release_date}}</p>
  <p>Director: {{movie.director}}</p>
</template>

<script lang="js">
const pageProps = ['movie']
export default { props: pageProps }
</script>
```
```js
// /pages/star-wars/movie.page.route.js
// Environment: Node.js

// Route String
export default '/star-wars/:movieId'
```
```js
// /pages/star-wars/movie.page.server.js
// Environment: Node.js

import fetch from 'node-fetch'

export async function onBeforeRender(pageContext) {
  // The route parameter of `/star-wars/:movieId` is available at `pageContext.routeParams`
  const { movieId } = pageContext.routeParams

  // `.page.server.js` files always run in Node.js; we could use SQL/ORM queries here.
  const response = await fetch(`https://swapi.dev/api/films/${movieId}`)
  let movie = await response.json()

  // Our render and hydrate functions we defined earlier pass `pageContext.pageProps` to
  // the root Vue component `Page`; this is where we define `pageProps`.
  const pageProps = { movie }

  // We make `pageProps` available as `pageContext.pageProps`
  return {
    pageContext: {
      pageProps
    }
  }
}

// By default `pageContext.*` are available only on the server. But our hydrate function
// we defined earlier runs in the browser and needs `pageContext.pageProps`; we use
// `passToClient` to tell `vite-plugin-ssr` to serialize and make `pageContext.pageProps`
// available to the browser.
export const passToClient = ['pageProps']
```

That's it for the tour and we have actually already seen most of the interface;
`vite-plugin-ssr` is not only flexible but also simple to use.

<ScaffoldCallToActionTour />
